using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class UIN_HeroEvolution : UIBaseNode
    {
        #region Template Generate,don't modify
        protected class UIB_UIN_HeroEvolution
        {
            #region ObjectBinding Generate
            public UnityEngine.RectTransform point { protected set; get; }
            public UnityEngine.GameObject infoPrevious { protected set; get; }
            public IQIGame.Onigao.Framework.ExText namePrevious { protected set; get; }
            public IQIGame.Onigao.Framework.ExText descPrevious { protected set; get; }
            public UnityEngine.GameObject attributeMould { protected set; get; }
            public UnityEngine.GameObject attributeMouldGrow { protected set; get; }
            public UnityEngine.GameObject update { protected set; get; }
            public UnityEngine.GameObject commonItem { protected set; get; }
            public UnityEngine.GameObject costMoney { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnUpdate { protected set; get; }
            public UnityEngine.GameObject finished { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<UnityEngine.RectTransform>("point", out var __tbv0);
                this.point = __tbv0;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("infoPrevious", out var __tbv1);
                this.infoPrevious = __tbv1;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("namePrevious", out var __tbv2);
                this.namePrevious = __tbv2;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("descPrevious", out var __tbv3);
                this.descPrevious = __tbv3;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("attributeMould", out var __tbv4);
                this.attributeMould = __tbv4;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("attributeMouldGrow", out var __tbv5);
                this.attributeMouldGrow = __tbv5;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("update", out var __tbv6);
                this.update = __tbv6;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("commonItem", out var __tbv7);
                this.commonItem = __tbv7;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("costMoney", out var __tbv8);
                this.costMoney = __tbv8;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnUpdate", out var __tbv9);
                this.btnUpdate = __tbv9;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("finished", out var __tbv10);
                this.finished = __tbv10;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify

        #region fields
        private ListScrollAdapter<UIN_CommonAttribute> baseAttrs = null;
        private ListScrollAdapter<UIN_CommonAttribute> growthAttrs = null;
        private ListScrollAdapter<UIN_CostItem> costItems = null;
        private UIN_CostMoney costMoney = null;

        private HeroData heroData;
        private CfgHeroStar cfgHeroStar;
        private CfgHeroStar nextCfgHeroStar;
        private CfgHeroStar maxCfgHeroStar;
        private bool isMaxStarLv = false;
        private UIEntityViewHelper entityHelper = null;
        private Transform starModel;
        #endregion fields

        #region properties

        protected UIB_UIN_HeroEvolution ui { get; set; }
        protected UIMsgDispatcher uiMsgDispatcher => this._msgDispatcher as UIMsgDispatcher;

        #endregion properties

        protected override void BeforeInit()
        {
            ui = new UIB_UIN_HeroEvolution();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            this.baseAttrs = this.InitListScroll<UIN_CommonAttribute>(this.ui.attributeMould, this.OnAttrChanged);
            this.growthAttrs = this.InitListScroll<UIN_CommonAttribute>(this.ui.attributeMouldGrow, this.OnGrowthAttrChanged);
            this.costItems = this.InitListScroll<UIN_CostItem>(this.ui.commonItem, this.OnCostItemChanged);
            this.costMoney = this.InitChildNode<UIN_CostMoney>(this.ui.costMoney);
        }

        protected override void OnShow()
        {

        }

        protected override void OnHide()
        {

        }

        /// <summary>
        /// 添加UGUI侦听
        /// </summary>
        protected override void AddUGUIListener()
        {
            this.ui.btnUpdate.onClick.AddListener(this.OnClickBtnUpdate);
        }

        /// <summary>
        /// 添加全局侦听（MsgDispatcher）
        /// </summary>
        protected override void AddMsgListeners()
        {

        }

        protected override void OnDispose()
        {
            this.ClearData();
            this.ClearModel();
        }

        #region methonds
        private void ClearData()
        {
            this.heroData = null;
            this.cfgHeroStar = null;
            this.nextCfgHeroStar = null;
            this.maxCfgHeroStar = null;
            this.isMaxStarLv = false;
        }

        public void Show(HeroData data)
        {
            this.Show();
            this.SetData(data);
            this.ShowStarModel();
            this.RefreshShow();
        }

        private void SetData(HeroData data)
        {
            this.heroData = data;
            this.maxCfgHeroStar = TableCenter.heroStar.MaxCfg(this.heroData.cid);
            this.RefreshData();
        }

        private void RefreshData()
        {
            int heroCid = this.heroData.cid;
            int heroStar = this.heroData.star;
            this.cfgHeroStar = this.heroData.cfgStar;
            this.isMaxStarLv = this.maxCfgHeroStar == this.cfgHeroStar;
            this.nextCfgHeroStar = this.isMaxStarLv ? null : TableCenter.heroStar.GetCfg(heroCid, heroStar + 1);
        }

        private void ShowStarModel()
        {
            var cfgHero = this.heroData.cfgData;
            this.ShowModel(cfgHero.StarPrefab_fullPath, this.ui.point);
        }

        private void ShowModel(string assetPath, Transform parent)
        {
            if (this.entityHelper == null)
                this.entityHelper = UIEntityViewHelper.NewFromPool().Sync(this.OnLoadedModel);

            this.starModel = null;
            this.entityHelper.ShowModel(assetPath, parent);
        }

        private void OnLoadedModel(UIEntityView uiModel)
        {
            this.ShowStarModelStarInfos(uiModel.transform);
        }

        private void ClearModel()
        {
            this.entityHelper?.Put2Pool();
            this.entityHelper = null;
            this.starModel = null;
        }

        private void ShowStarModelStarInfos(Transform starModel)
        {
            this.starModel = starModel;
            this.RefreshStarModelStarInfos();
        }

        private void RefreshStarModelStarInfos()
        {
            if (this.starModel == null)
            {
                return;
            }
            Transform starsRoot = this.starModel.Find("Stars");
            int childCount = starsRoot?.childCount ?? 0;
            if (childCount <= 0)
            {
                return;
            }
            int currStarIndex = this.heroData.star;
            Transform starRoot = null;
            bool isPreview, isLight;
            GameObject gobj = null;
            for (int i = 0; i < childCount; i++)
            {
                starRoot = starsRoot.GetChild(i);
                gobj = starRoot.GetChild(1).gameObject;
                isPreview = (i == currStarIndex + 1);
                gobj.SetActive(isPreview);

                gobj = starRoot.GetChild(2).gameObject;
                isLight = (i <= currStarIndex);
                gobj.SetActive(isLight);
            }
        }

        private void RefreshShow()
        {
            this.ShowSkillPrevious();
            this.ShowBaseAttributes();
            this.ShowGrouthAttributes();
            this.ShowUpStarState();
        }

        private void ShowSkillPrevious()
        {
            var cfgStar = this.nextCfgHeroStar;
            bool isActive = cfgStar?.IsShowFeature ?? false;
            if (isActive)
            {
                this.ui.namePrevious.text = cfgStar.SkillName;
                this.ui.descPrevious.text = cfgStar.SkillEffectText;
            }
            this.ui.infoPrevious.SetActive(isActive);
        }

        private void ShowBaseAttributes()
        {
            var cfgStar = this.cfgHeroStar;
            this.baseAttrs.RefillCells(cfgStar.AttTypes.Count);
        }

        private void OnAttrChanged(UIN_CommonAttribute item, int index)
        {
            var cfgStar = this.cfgHeroStar;
            int attrCid = cfgStar.AttTypes[index];
            int attrValue = this.heroData.GetAttr(attrCid);

            int changNum = 0;
            if (this.nextCfgHeroStar != null)
            {
                int currValue = cfgStar.AttValues[index];
                int currGrowth = cfgStar.DeltaAttrValues[index];
                int nextValue = this.nextCfgHeroStar.AttValues[index];
                int nextGrowth = this.nextCfgHeroStar.DeltaAttrValues[index];
                changNum = (nextValue - currValue) + (nextGrowth - currGrowth) * this.heroData.level;
            }
            item.Show(attrCid, attrValue, changNum);
        }

        private void ShowGrouthAttributes()
        {
            var cfgStar = this.cfgHeroStar;
            this.growthAttrs.RefillCells(cfgStar.AttTypes.Count);
        }

        private void OnGrowthAttrChanged(UIN_CommonAttribute item, int index)
        {
            var cfgStar = this.cfgHeroStar;
            int attrCid = cfgStar.AttTypes[index];
            int currGrowth = cfgStar.DeltaAttrValues[index];

            int changNum = 0;
            if (this.nextCfgHeroStar != null)
            {
                int nextGrowth = this.nextCfgHeroStar.DeltaAttrValues[index];
                changNum = (nextGrowth - currGrowth);
            }

            item.Show(attrCid, currGrowth, changNum);
        }

        private void ShowUpStarState()
        {
            this.ShowUpStarInfo();
            this.ui.finished.SetActive(this.isMaxStarLv);
            if (!this.isMaxStarLv)
            {
                this.ShowCostItems();
                this.ShowCostMoney();
            }
        }

        private void ShowUpStarInfo()
        {
            this.ui.update.SetActive(!this.isMaxStarLv);
        }

        private void ShowCostItems()
        {
            var cfgStar = this.cfgHeroStar;
            int cntCostItems = cfgStar.Cost.Count / APIUIConst.CostDefaultSpacing;
            this.costItems.RefillCells(cntCostItems);
        }

        private void OnCostItemChanged(UIN_CostItem item, int index)
        {
            var cfg = this.cfgHeroStar;
            int kStart = index * APIUIConst.CostDefaultSpacing;
            int cid = cfg.Cost[kStart];
            int numCost = cfg.Cost[kStart + 1];
            item.Show(cid, numCost);
        }

        private void ShowCostMoney()
        {
            var cfg = this.cfgHeroStar;
            if (cfg.GoldCost.Count < 2)
            {
                this.costMoney.Hide();
            }
            else
            {
                this.costMoney.Show(cfg.GoldCost[0], cfg.GoldCost[1]);
            }
        }

        private void OnClickBtnUpdate()
        {
            if (!this.costMoney.CheckIsEnough())
            {
                return;
            }
            this.SendUpdateHeroStar().Forget();
        }

        private async UniTaskVoid SendUpdateHeroStar()
        {
            var result = await HeroModule.NetCore.CS_upStar(this.heroData.cid);
            if (result.IsSuccess && this.isActive)
            {
                HeroModule.Instance.UpHeroByPOD(result.heroPOD);
                this.RefreshData();
                this.RefreshStarModelStarInfos();
                this.RefreshShow();
                this.OpenUI<UIHeroEvolutionPop>(UD_HeroEvolutionPop.Create(this.heroData));
            }
        }
        #endregion methonds
    }
}
